package com.ywk.base.javaBase.javaKeywords;

/**
 * @Author zbh
 * @Date 2023/1/31
 */
public class StringTest {
    public static void main(String[] args) {
        String str=new String("aaa");//只要使用 new 方法，便需要创建新的对象。(此时创建了两个对象，因为常量池中没有“aaa”)
        String s="aaa";//常量池中有该字符串
        System.out.println(str==s);//false，str指向堆内存地址，s指向池中的字符串内存地址，不相同
        //常量池中已经存在"aaa",所以str.intern()返回的是常量池中该字符串的引用
        System.out.println(str.intern()==s);//true
        String a1 = new String("a"); // 创建"a"，并把"a"缓存到常量池，占用2块内存空间
        String a2 = new String("b"); // 创建"b"，并把"b"缓存到常量池，占用2块内存空间
        System.out.println((a1+a2).intern() == "ab");//true
        /*在堆中连接生成了"ab"，调用intern()后发现常量池没有"ab"，那么就把指向堆中的"ab"的引用放入常量池，
        返回值为堆中这个引用。当执行这个表达式的时候，从左到右执行，左边是常量池指向堆中的引用，右边也是直接使用常量池的"ab"
        (其实就是指向堆中"ab"的引用)，直接返回这个引用，两边引用都是堆里面连接生成的"ab"的地址，所以打印出true。*/

        String str1 = "abcd"; // 常量池创建"abcd"
        String str2 = "abcd"; // str2还是上一步的"abcd"
        String str3 = "ab" + "cd"; //只创建了一个对象，程序做了优化
        // 常量池创建"ab"和"cd"，连接过程编译器直接优化成"abcd"，而常量池已经了"abcd"，所以str3和str1都指向"abcd"
        String str4 = "ab"; // 常量池已经有了"ab"*/
        str4 += "cd"; // str4+"cd"连接的字符串编译器不能优化，所以此时str4指向堆中的"abcd"
        /* 因为"ab"是str4引用的，如果是两个变量s1="ab", s2="cd",s1+s2连接，那么只有用final修饰的指向"ab"的s1和
        final修饰的指向"cd"的s2相连接才能优化成"abcd"*/
        // 如果只有一个变量s1和常量池的常量连接s1+"cd"，这个变量s1也需要final修饰才会优化成"abcd"
        System.out.println(str1 == str2); // true
    }
}
